/*
 * psMqtt.cpp
 *
 *  Created on: Nov 16, 2021
 *      Author: tau
 */

#include <net/psMqtt.h>
#include "malloc.h"
#include <stdlib.h>
#include <string.h>
#if !defined(WIN32)
#include <unistd.h>
#else
#include <windows.h>
#endif

static MQTTClient_deliveryToken deliveredtoken;
static void delivered(void *context, MQTTClient_deliveryToken dt){
    printf("Message with token value %d delivery confirmed\n", dt);
    deliveredtoken = dt;
}

static int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message){
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("   message: %.*s\n", message->payloadlen, (char*)message->payload);
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    return 1;
}

static void connlost(void *context, char *cause){
    printf("\nConnection lost\n");
    printf("     cause: %s\n", cause);
}

#define TIMEOUT     5000L
psMqtt::psMqtt()
{
    int rc;
    pthread_t mqttPthread;
    if((rc = readConfig()) == 0){
        printf("mqtt config file read success!\r\n");
        if((rc = createMqttClient()) == 0){
            printf("mqtt client create success!\r\n");
            isConnected =true;
            pthread_create(&mqttPthread, NULL, background, 0);
        }
        else{
            printf("mqtt client create error!\r\n");
        }

    }else{
        printf("mqtt config file read error!\r\n");
    }


}

psMqtt::~psMqtt() {
	// TODO Auto-generated destructor stub
}



int psMqtt::readConfig(void){
    FILE *f;//输入文件
    long len;//文件长度
    char *content;//文件内容
    f=fopen("/home/pussion/app/config.json","rb");
    fseek(f,0,SEEK_END);
    len=ftell(f);
    fseek(f,0,SEEK_SET);
    content=(char*)malloc(len+1);
    fread(content,1,len,f);
    fclose(f);

    json=cJSON_Parse(content);
    if (!json) {
        printf("Error before: [%s]\n",cJSON_GetErrorPtr());
        return  -1;
    }
    snprintf(mcb.host,128,"%s",cJSON_GetObjectItem(json,"host")->valuestring);
    snprintf(mcb.clientID,32,"%s",cJSON_GetObjectItem(json,"clientID")->valuestring);
//    snprintf(mcb.pubTopic,32,"%s",cJSON_GetObjectItem(json,"pubTopic")->valuestring);
//    snprintf(mcb.subTopic,32,"%s",cJSON_GetObjectItem(json,"subTopic")->valuestring);
//    snprintf(mcb.user,32,"%s",cJSON_GetObjectItem(json,"user")->valuestring);
//    snprintf(mcb.password,32,"%s",cJSON_GetObjectItem(json,"password")-> valuestring);

    printf("host:%s\r\n",mcb.host);
    printf("clientID:%s\r\n",mcb.clientID);
    return 0;
}

int psMqtt::createMqttClient(void){
    int rc;
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
    if((rc = MQTTClient_create(&mClientb.client, mcb.host, mcb.clientID,MQTTCLIENT_PERSISTENCE_NONE, NULL)!=MQTTCLIENT_SUCCESS)){
            return -1;
    }
    if ((rc = MQTTClient_setCallbacks(mClientb.client, NULL, connlost, msgarrvd, delivered)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to set callbacks, return code %d\n", rc);
    }
    conn_opts.keepAliveInterval = 20;
    conn_opts.cleansession = 1;
    conn_opts.username = mcb.user; //将用户名写入连接选项中
    conn_opts.password = mcb.password;//将密码写入连接选项中
    if ((rc = MQTTClient_connect(mClientb.client, &conn_opts)) != MQTTCLIENT_SUCCESS){
        printf("pubClient failed to connect, return code %d\n", rc);
        return -1;
    }
    if ((rc = MQTTClient_subscribe(mClientb.client, mcb.subTopic, 0)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to subscribe, return code %d\n", rc);
        return -1;
    }
    return 0;
}

int psMqtt::sendMsg(char* data){
    int rc;
    MQTTClient_message pubmsg = MQTTClient_message_initializer;
    MQTTClient_deliveryToken token;
    pubmsg.payload = (void*)data;
    pubmsg.payloadlen = (int)strlen(data);
    pubmsg.qos = 0;
    pubmsg.retained = 0;
    if(isConnected){
        if ((rc = MQTTClient_publishMessage(mClientb.client, mcb.pubTopic, &pubmsg, &token)) != MQTTCLIENT_SUCCESS){
             printf("Failed to publish message, return code %d\n", rc);
        }
        printf("Waiting for up to %d seconds for publication of %s\n"
                "on topic %s for client with ClientID: %s\n",
                (int)(TIMEOUT/1000), (char*)pubmsg.payload, mcb.pubTopic, mcb.clientID);
        rc = MQTTClient_waitForCompletion(mClientb.client, token, TIMEOUT);
        printf("Message with delivery token %d delivered\n", token);
    }else{
        printf("------- mqtt disconneted! -------\r\n");
    }
    return 0;
}

void* psMqtt:: background(void* arg){
    MQTTClient_yield();
    usleep(100000);
    return 0;
}
